----------------------------------------------------------------------------------
-- Company: 
-- Engineer: 
-- 
-- Create Date:    10:11:49 09/27/2013 
-- Design Name: 
-- Module Name:    mult_div - Behavioral 
-- Project Name: 
-- Target Devices: 
-- Tool versions: 
-- Description: 
--
-- Dependencies: 
--
-- Revision: 
-- Revision 0.01 - File Created
-- Additional Comments: 
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

-- does multiplication and division depending on divControl
-- divControl = '1' then divide else multiply
-- also handles signed and unsigned operands depending on signControl
-- signControl = '1' treat operands as signed, else treat as unsigned
-- also handles conversion to final result:
-- e.g. if signed multiplication 
entity mult_div is
	port(	signControl, divControl, clock : in STD_LOGIC;
			a, b : in STD_LOGIC_VECTOR(31 downto 0);
			result : out STD_LOGIC_VECTOR(63 downto 0));
end mult_div;

architecture Behavioral of mult_div is
--	component mult32x32 is
--		port(	clk, load : in STD_LOGIC;
--				A, B : in STD_LOGIC_VECTOR(31 downto 0);
--				result : out STD_LOGIC_VECTOR(63 downto 0));
--	end component;
	
	component multiplier_noCycle is
		port (clk 		: in STD_LOGIC;
				a, b 		: in STD_LOGIC_VECTOR(31 downto 0);
				output 	: out STD_LOGIC_VECTOR(63 downto 0));  
	end component;
	
	component divider32 is
    Port ( clk : in  STD_LOGIC;
			  load : in STD_LOGIC;
           numerator : in  STD_LOGIC_VECTOR (31 downto 0);
           denominator : in  STD_LOGIC_VECTOR (31 downto 0);
           quotient : out  STD_LOGIC_VECTOR (31 downto 0);
           remainder : out  STD_LOGIC_VECTOR (31 downto 0));
	end component;
	signal load : STD_LOGIC := '0';
	signal product : STD_LOGIC_VECTOR(63 downto 0) := X"0000000000000000";
	signal quotient, remainder : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
	signal aLoad, bLoad : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
begin
	mult : multiplier_noCycle port map(clock, aLoad, bLoad, product);
	div : divider32 port map(clock, load, aLoad, bLoad, quotient, remainder);
process(clock)
	variable signControlReg, divControlReg : STD_LOGIC := '0';
	variable aInitial, bInitial : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
	variable quotientComplement : STD_LOGIC_VECTOR(31 downto 0) := X"00000000";
begin
	if clock'event and clock = '1' then
		if a /= aInitial or b /= bInitial or signControl /= signControlReg or divControl /= divControlReg then
			aInitial := a;
			bInitial := b;
			divControlReg := divControl;
			signControlReg := signControl;
			load <= '1';
			
			if signControl = '1' and a(31) = '1' then
				aLoad <= NOT(a) + 1;
			else	
				aLoad <= a;
			end if;
			
			if signControl = '1' and b(31) = '1' then
				bLoad <= NOT(b) + 1;
			else
				bLoad <= b;
			end if;
		else
			load <= '0';
		end if;
		
		if signControl = '1' and 
			((a(31) = '1' and b(31) = '0') or (a(31) = '0' and b(31) = '1')) then
			if divControl = '0' then
				result <= NOT(product) + 1;
			else
				quotientComplement := NOT(quotient) + 1;
				result <= quotientComplement & remainder;
			end if;
		else
			if divControl = '0' then
				result <= product;
			else
				result <= quotient & remainder;
			end if;
		end if;
	end if;
end process;
end Behavioral;

